package org.wheres2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jivesoftware.smack.XMPPException;
import org.wheres2.core.ServiceClient;
import org.wheres2.core.contactlist.ContactManager;
import org.wheres2.core.contactlist.InvalidContactNameException;
import org.wheres2.eventmanager.ConnectionErrorManager;
import org.wheres2.eventmanager.PresenceManager;
import org.wheres2.utils.MySimpleAdapter;

import android.os.Bundle;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;

/**
 * La classe implementa l'activity ContactsDisplay che visualizza la lista contatti
 * 
 * @author 
 *
 */
public class ContactsDisplay extends ExpandableListActivity implements PresenceManager,ConnectionErrorManager{
	
	private ServiceClient client;
	private Intent serviceIntent;
	private boolean boundToService = false;
	
	private MySimpleAdapter mAdapter;
	private List<Map<String,String>> groupData;
	private List<List<Map<String,String>>> childData;
    private ExpandableListView listView;
    private EditText userEditText;
    private EditText nameEditText;
    private Button startAndStop;
    private boolean isOnScreen = false;

	
	private ServiceConnection communicatorConnection = new ServiceConnection(){

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			client = ((ServiceClient.ServiceClientBinder)service).getService();
			boundToService = true;
			client.addPresenceListener(ContactsDisplay.this);
			client.addConnectionErrorListener(ContactsDisplay.this);
			client.startLocationService();
			if(!client.isLocationStarted())
				client.startLocation();
			createList();	
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			client = null;
			boundToService = false;
		}	
	};
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_contact_list);
		listView = (ExpandableListView) getExpandableListView();
		startAndStop = (Button) findViewById(R.id.StartAndStopLocalizationButton);

		
	}
	
	@Override
	protected void onResume() {
		if(!this.boundToService){
			serviceIntent = new Intent(ContactsDisplay.this, ServiceClient.class);
			bindService(serviceIntent, communicatorConnection, Context.BIND_AUTO_CREATE);			
		}
		this.isOnScreen = true;
		super.onResume();
	}
	
	
	@Override
	protected void onPause() {
		if (this.boundToService){
			this.client.removePrecenceListener();
			unbindService(communicatorConnection);
			this.boundToService = false;
			this.isOnScreen = false;
		}
		super.onPause();
	}
	
	
	
	@Override
	 public boolean onCreateOptionsMenu(Menu menu) {
	  
	  MenuInflater inflater = getMenuInflater();
	  inflater.inflate(R.menu.contact_list, menu);
	  return true;
	 }
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		switch(item.getItemId()){
			case R.id.AddNewContact:
				this.addContactAction();
				return true;
			case R.id.Exit:
				this.closeApp();
				return true;
				default:
					super.onOptionsItemSelected(item);
			
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * 
	 * Creazione della lista dei contatti
	 * 
	 */
	private void createList(){
		
		groupData = new ArrayList<Map<String, String>>();
		Map<String,String> on = new HashMap<String,String>();
		Map<String,String> off= new HashMap<String,String>();
		
		on.put(ContactManager.NAME, "Online");
		groupData.add(on);
		
		off.put(ContactManager.NAME, "Offline");
		groupData.add(off);
		
		childData = this.client.getContactList();		
		
		mAdapter = new MySimpleAdapter(
				this,
                groupData,
                R.layout.my_simple_expandable_list_item_1,
                new String[] { ContactManager.NAME},
                new int[] { R.id.GroupNameTextView},
                childData,
                R.layout.my_simple_expandable_list_item_2,
                new String[] { ContactManager.NAME, ContactManager.USERNAME, 
								ContactManager.POSITION_REQUEST, ContactManager.POSITION_SENT},
                new int[] { R.id.NameTextView, R.id.UsernameTextView, R.id.childImageRequest, R.id.childImagePosition}
				);
		
		
		setListAdapter(mAdapter);
		listView.expandGroup(0);
		listView.expandGroup(1);
		 
	}

	/**
	 * 
	 * @see org.wheres2.eventmanager.PresenceManager#onContactListChanged()
	 * 
	 */
	@Override
	public void onContactListChanged() {
		
		Thread update = new Thread(new Runnable(){

			@Override
			public void run() {
				mAdapter.notifyDataSetChanged();
				
			}
			
		});
		 
		runOnUiThread(update);
		
	}
	
	/**
	 * Rimuove il contatto dalla lista
	 * 
	 * @param user: usermane in formato JID del contatto da rimuovere
	 */
	public void removeContactAction(String user){
			
		try {
			client.removeContactFromServer(user);
		} catch (InvalidContactNameException e) {
			e.printStackTrace();
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 
	 * Visualizza la dialogo di inserimento di un nuovo contatto
	 * 
	 */
	public void addContactAction(){
		
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		LayoutInflater mInflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
		View dialogView = mInflater.inflate(R.layout.add_contact_dialog, null);
		userEditText = (EditText)dialogView.findViewById(R.id.AddContactUsername);
		nameEditText = (EditText)dialogView.findViewById(R.id.AddContactName);
		
		builder.setView(dialogView)
				.setPositiveButton(R.string.AddNewContactDialogButton, new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						addContactToServer(userEditText.getText().toString(), nameEditText.getText().toString());						
					}
				})
				.setNegativeButton(R.string.NoDialogButton, new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						
					}
				});
		builder.create().show();
		
		
	}
	
	/**
	 * 
	 * Richiesta di aggiunta contatto al Server
	 * 
	 * @param username: username in formato JID del contatto da inserire
	 * @param name: nome associato al contatto da inserire
	 * 
	 */
	public void addContactToServer(String username, String name){
		try {
			client.addContactToServer(username, name);
		} catch (InvalidContactNameException e) {
			e.printStackTrace();
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 
	 * Chiude l'applicazione
	 * 
	 */
	private void closeApp(){
		client.removeConnectionErrorListener(this);
		client.disconnect();
		client.stopLocationService();
		client.stopSelf();
		this.finish();
	}
	
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
	    if ((keyCode == KeyEvent.KEYCODE_BACK)) {
	        Intent i = new Intent(Intent.ACTION_MAIN);
	        i.addCategory(Intent.CATEGORY_HOME);
			if(this.client.isLocationStarted())
				this.client.stopLocation();
	        startActivity(i);
	        return false;
	        }
		return super.onKeyDown(keyCode, event);
	}
	
	/**
	 * 
	 * Operazioni associate ai pulsanti "Inizia/Ferma Localizzazione"
	 * 
	 * @param view
	 */
	public void startAndStopLocalization(View view){
		if(this.client.isLocationStarted()){
			this.client.stopLocation();
			this.startAndStop.setText(R.string.StartLocalization);
		}else{
			this.client.startLocation();			
			this.startAndStop.setText(R.string.StopLocalization);
		}
			
	}
	
	/**
	 * Operazioni associate al pulsante Radar
	 * 
	 * @param view
	 */
	public void onClickRadar(View view){
		  Intent radarIntent = new Intent(this,Radar.class);
		  radarIntent.putExtra(Radar.THROWER, Radar.CONTACT_LIST_THROWER);
		  startActivity(radarIntent);
		 }
	
	/**
	 * 
	 * @see org.wheres2.eventmanager.ConnectionErrorManager#closeOnConnectionError()
	 * 
	 */
	@Override
	public void closeOnConnectionError() {
		
		if(this.isOnScreen)
			runOnUiThread(new Runnable() {
				
				@Override
				public void run() {
					
					close();
					
				}
			});
		else
			this.finish();		
	}
	
	/**
	 * 
	 * Operazioni eseguite a seguito di un errore nella connessione
	 * 
	 */
	private void close(){
		
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage(R.string.ConnectionErrorDialogText)
					.setTitle(R.string.ConnectionErrorDialogTitle)
					.setPositiveButton(R.string.ExitMenu, new DialogInterface.OnClickListener() {
				
						@Override
						public void onClick(DialogInterface dialog, int which) {
							client.stopLocationService();
							if (boundToService){
								unbindService(communicatorConnection);
								boundToService = false;
							}
							client.stopSelf();
							ContactsDisplay.this.finish();
							dialog.dismiss();
						}
			});
			AlertDialog connectionError = builder.create();
			connectionError.show();	
			
	}
	
	
}
